<template>
  <div :style="{width:'100%'}">
    <div class="larry-cropper-img-box" :style="{width:'100%',height:`${cropBoxHieght}px`}">
      <img
        :ref="cropperRef"
        :id="cropperRef"
        :src="imgSrc"
        :style="{width:'100%',height:`${cropBoxHieght}px`}"
      />
    </div>
    <div :style="{display: 'flex'}">
      <span v-if="needCrop" :style="{marginRight: '30px'}">{{`推荐长宽比${recommendedRatio}`}}</span>
      <span v-if="needCrop" :style="{marginRight: '30px'}">允许误差{{this.permissibleErrors}}px</span>
      <span v-if="currentCropWidth && currentCropHeith" :style="{marginRight: '30px'}">
        <span>当前比例{{currentCropWidth}}px</span>
        <span style="margin: 0 5px">:</span>
        <span>{{currentCropHeith}}px</span>
      </span>
      <span
        v-if="uploadSuccess"
        :style="{float: 'right', color: '#45cc3e', flex: 1, textAlign: 'right'}"
      >上传成功</span>
    </div>
    <div style="margin-top: 5px">
      <div class="larry-cropper-menubar">
        <Tooltip content="移动图片">
          <Icon type="md-move" @click="handleMoveImg" />
        </Tooltip>
        <Tooltip v-if="needCrop" content="剪辑" style="float: right">
          <Icon type="md-crop" @click="handleCropImg" />
        </Tooltip>
      </div>
      <div class="larry-cropper-menubar">
        <Tooltip content="放大">
          <Icon type="md-add" @click="handleEnlarge" />
        </Tooltip>
        <Tooltip content="缩小" style="float: right">
          <Icon type="md-remove" @click="handleNarrow" />
        </Tooltip>
      </div>
      <div class="larry-cropper-menubar">
        <Tooltip content="显示截图框">
          <Icon type="md-checkmark" @click="handleShowCrop" />
        </Tooltip>
        <Tooltip content="关闭截图框" style="float: right">
          <Icon type="md-close" @click="handleCleanCrop" />
        </Tooltip>
      </div>
      <div class="larry-cropper-menubar">
        <Tooltip content="顺时针旋转45度">
          <Icon type="md-refresh" @click="handleRotate" />
        </Tooltip>
        <Tooltip content="左右翻转">
          <Icon style="margin-right: 5px" type="md-swap" @click="handlescale('X')" />
        </Tooltip>
        <Tooltip content="上下翻转" style="float: right">
          <Icon class="flipy" type="md-swap" @click="handlescale('Y')" />
        </Tooltip>
      </div>
      <!-- <div class="larry-cropper-menubar">
        <Tooltip content="禁用截图">
          <Icon type="md-lock" @click="handleDisableCrop"/>
        </Tooltip>
        <Tooltip content="启用截图" style="float: right">
          <Icon type="md-unlock" @click="handleEnableCrop"/>
        </Tooltip>
      </div>-->
      <div class="larry-cropper-menubar">
        <Tooltip content="重置">
          <Icon type="md-sync" @click="handleReset" />
        </Tooltip>
        <Tooltip content="选择文件">
          <Upload action="/upload" :before-upload="handleBeforeUpload">
            <Icon type="md-arrow-round-up" />
          </Upload>
        </Tooltip>
        <Tooltip content="上传">
          <Icon type="ios-cloud-upload" @click="handleUpload" />
        </Tooltip>
        <!-- <Tooltip content="销毁" :style="{float: 'right',marginLeft: '8px'}">
          <Icon type="md-power" @click="handleDestroy"/>
        </Tooltip>-->
      </div>
    </div>
  </div>
</template>

<script>
import Uuid from "uuid";
import appService from "@/utils/appService";
import request from "@/utils/request";
import moment from "moment";
import config from "@/utils/config";
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";
import { Button, Icon, Tooltip, Upload, Message } from "view-design";
export default {
  props: {
    value: {
      type: String
    },
    /** 是否需要编辑 */
    needCrop: {
      type: Boolean,
      default: false
    },
    /** 剪辑高度,为0时不限制 */
    cropHeight: {
      type: Number
    },
    /** 剪辑宽度,为0时不限制 */
    cropWidth: {
      type: Number
    },
    /** 剪辑框高度，单位px */
    cropBoxHieght: {
      type: Number,
      default: 260
    },
    /** 允许误差像素 */
    permissibleErrors: {
      type: Number,
      default: 50
    }
  },
  components: { Button, Icon, Tooltip, Upload },
  model: {
    prop: "value",
    event: ["onChange"]
  },
  watch: {
    value: function(newValue, oldValue) {
      /** 如果是上传成功的改变 */
      if (this.isUploadSuccessChange) {
        this.isUploadSuccessChange = false;
      } else {
        this.currentCropWidth = null;
        this.currentCropHeith = null;
        this.uploadSuccess = false;
        if (newValue && newValue !== "") {
          newValue = this.replaceUrl(newValue);
        }
        this.imgSrc = newValue;
        this.cropper.replace(newValue);
      }
    }
  },
  data: function() {
    return {
      imgSrc: "",
      /** 上传成功 */
      uploadSuccess: false,
      /** 是否是上传成功的改变 */
      isUploadSuccessChange: false,
      /** cropper实例 */
      cropper: null,
      cropperRef: Uuid.v1(),
      /** 当前编辑框宽度 */
      currentCropWidth: null,
      /** 当前编辑框高度 */
      currentCropHeith: null,
      /** 截图框是否关闭 */
      cropBoxClose: true
    };
  },
  computed: {
    /** 计算编辑的长宽比 */
    aspectRatio: function() {
      if (
        !this.cropHeight ||
        this.cropHeight === 0 ||
        !this.cropWidth ||
        this.cropWidth === 0
      ) {
        return null;
      } else {
        return this.cropWidth / this.cropHeight;
      }
    },
    recommendedRatio: function() {
      if (this.aspectRatio) {
        return this.cropWidth + "px:" + this.cropHeight + "px";
      } else {
        return "自由比例";
      }
    }
  },
  mounted() {
    let image = document.getElementById(this.cropperRef);
    let offsetHeight = image.offsetHeight;
    image.addEventListener("crop", event => {
      let detail = event.detail;
      if (
        detail.height === 0 &&
        detail.rotate === 0 &&
        detail.scaleX === 1 &&
        detail.scaleY === 1 &&
        detail.width === 0 &&
        detail.x === 0 &&
        detail.y === 0
      ) {
        this.cropBoxClose = true;
      } else {
        this.cropBoxClose = false;
      }
      this.currentCropWidth = detail.width.toFixed(2);
      this.currentCropHeith = detail.height.toFixed(2);
    });
    this.cropper = new Cropper(image, {
      aspectRatio: 1,
      viewMode: 1,
      dragMode: "crop",
      initialAspectRatio: null,
      /** 定义裁剪框的初始纵横比。默认情况下，它与画布（图像包装器）的宽高比相同 */
      aspectRatio: this.aspectRatio,
      data: null,
      /** 是否自动生成截图框 */
      autoCrop: false,
      background: true,
      zoomable: true,
      guides: true
    });
    if (this.value && this.value !== "") {
      this.imgSrc = this.value;
      this.cropper.replace(this.replaceUrl(this.value));
    }
  },
  methods: {
    getUploadTicket: async function() {
      /** http://tgw.wiiqq.com/test/api/cos/ticket/get_ticket?bucket=manager */
      /** https://gw.ybsjyyn.com/api/cos/ticket/get_ticket?bucket=manager */
      let responst = await appService.getRequest(
        "https://gw.ybsjyyn.com/api/cos/ticket/get_ticket?bucket=manager"
      );
      let ticket = responst.data.data.ticket;
      return ticket;
    },
    getTempFileName() {
      let fileName = moment().format("YYYYMMDDHHmmSSS");
      fileName = fileName + Uuid.v1();
      let subfix;
      if (this.file) {
        let file = this.file;
        subfix = file.name.substring(
          file.name.lastIndexOf("."),
          file.name.length
        );
      } else {
        subfix = this.imgSrc.substring(
          this.imgSrc.lastIndexOf("."),
          this.imgSrc.length
        );
      }
      fileName = fileName + subfix;
      return fileName;
    },
    /** 销毁 */
    handleDestroy() {
      if (this.cropper) {
        this.cropper.destroy();
      }
    },
    /** 重置 */
    handleReset() {
      if (this.cropper) {
        this.cropper.reset();
      }
    },
    handleMoveImg() {
      if (this.cropper) {
        this.cropper.setDragMode("move");
      }
    },
    handleCropImg() {
      if (this.cropper) {
        this.cropper.setDragMode("crop");
      }
    },
    /** 处理放大 */
    handleEnlarge() {
      if (this.cropper) {
        this.cropper.zoom(0.1);
      }
    },
    /** 处理缩小 */
    handleNarrow() {
      if (this.cropper) {
        this.cropper.zoom(-0.1);
      }
    },
    /** 处理显示截图框 */
    handleShowCrop() {
      if (this.cropper) {
        this.cropper.crop();
      }
    },
    /** 处理关闭截图框 */
    handleCleanCrop() {
      if (this.cropper) {
        this.cropper.clear();
      }
    },
    /** 处理重置 */
    handleReset() {
      if (this.cropper) {
        this.cropper.reset();
      }
    },
    /** 处理顺时针旋转45度 */
    handleRotate() {
      if (this.cropper) {
        this.cropper.rotate(45);
      }
    },
    /** 处理翻转 */
    handlescale(type) {
      if (this.cropper) {
        this.cropper[`scale${type}`](-this.cropper.getData()[`scale${type}`]);
      }
    },
    /** 禁用截图框 */
    handleDisableCrop() {
      if (this.cropper) {
        this.cropper.disable();
      }
    },
    /** 启用截图框 */
    handleEnableCrop() {
      if (this.cropper) {
        this.cropper.enable();
      }
    },
    /** 替换url,处理跨域问题 */
    replaceUrl(url) {
      return url;
    },
    /** 上传前处理 */
    handleBeforeUpload(file) {
      if (file.size > (2 * 1024 * 1024)) {
        Message.error("图片尺寸不能超过2M");
        return;
      }
      this.file = file;
      this.uploadSuccess = false;
      this.currentCropWidth = null;
      this.currentCropHeith = null;
      this.cropBoxClose = true;
      let vm = this;
      let reader = new FileReader();
      //将文件以Base64形式读入
      reader.readAsDataURL(file);
      reader.onload = function(event) {
        vm.cropper.replace(this.result);
      };
      return false;
    },
    handleUpload() {
      let vm = this;
      let croppedCanvas = this.cropper.getCroppedCanvas();
      this.currentCropWidth = croppedCanvas.width;
      this.currentCropHeith = croppedCanvas.height;
      if (this.needCrop) {
        if (
          Math.abs(this.currentCropWidth - this.cropWidth) >
          this.permissibleErrors
        ) {
          Message.error(`宽度误差超过${this.permissibleErrors}px`);
          return;
        }
        if (
          Math.abs(this.currentCropHeith - this.cropHeight) >
          this.permissibleErrors
        ) {
          Message.error(`高度误差超过${this.permissibleErrors}px`);
          return;
        }
      }
      croppedCanvas.toBlob(async blob => {
        let formData = new FormData();
        //如果截图框是关闭状态,则上传原图
        if (vm.cropBoxClose) {
          formData.append("fileContent", this.file);
        }
        formData.append("fileContent", blob);
        formData.append("op", "upload");
        formData.append("insertOnly", 0);
        /** 失败重试10次 */
        for (let i = 0; i < 10; i++) {
          let ticket = await this.getUploadTicket();
          let uploadUrl = config.uploadApiProxy + "/" + this.getTempFileName();
          uploadUrl += `?sign=${ticket}`;
          let responst = await request.postRequest(uploadUrl, formData);
          if (responst.status === 200) {
            let sourceUrl = responst.data.data.source_url;
            let newUlr = this.replaceUrl(sourceUrl);
            /** 上传成功 */
            this.uploadSuccess = true;
            /** 是上传成功的改变 */
            this.isUploadSuccessChange = true;
            /** 图片重新赋值src */
            this.imgSrc = newUlr;
            /** 编辑框重载 */
            this.cropper.replace(newUlr);
            this.handleCleanCrop();
            /** 调用onChange事件 */
            this.$emit("onChange", sourceUrl);
            break;
          }
        }
      });
    }
  }
};
</script>
<style lang="less">
.larry-cropper-menubar {
  height: 35px;
  line-height: 35px;
  font-size: 20px;
  background-color: #007bff;
  color: #ffffff;
  display: inline-block;
  border-radius: 5px;
  padding: 0 5px;
}
.larry-cropper-img-box {
  background-image: url("");
}
.flipy {
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
  -moz-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg);
}
</style>
